#include "theater.h"
#include "synch.h"
#include "system.h"

//the manager told the ticketclerk to work
void ticketClerk_startWork(unsigned int ticketclerk_workno)
{
    DBGPRINT(DEBUG_TRACE,"ticket clerk %d is going to work\n",ticketclerk_workno);
    while(1)
    {
        DBGPRINT(DEBUG_INFO, " ticketclerk %d  \n ", ticketclerk_workno);
checkOff:
        ticketClerkMsgLock[ticketclerk_workno]->Acquire();
        if(OFF_WORK==ticketclrk_off[ticketclerk_workno]||ADD_NEWLINE==ticketclrk_addNewline[ticketclerk_workno])
        {
            DBGPRINT(DEBUG_INFO, "the manager tell me to break, ticketclerk %d wait here \n ", ticketclerk_workno);
			printf("TicketClerk [%d] is going on break.\n", ticketclerk_workno);
            //before I break, I need to check if there is anyone in my line, if any, I need to ask them to find a line instead

            if(ticketclrk_cus_count[ticketclerk_workno]>0)
            {
                ticketclerkline_cv[ticketclerk_workno]->Broadcast(ticketClerkLineLock);
                ticketclrk_addNewline[ticketclerk_workno]=NONEWLINE;
            }
            if(OFF_WORK==ticketclrk_off[ticketclerk_workno])
            {
                ticketclrk_cus_count[ticketclerk_workno]=0;
                ticketclrk_state[ticketclerk_workno]=0;
            }
            ticketclerkMsg_cv[ticketclerk_workno]->Wait(ticketClerkMsgLock[ticketclerk_workno]);
            ticketClerkMsgLock[ticketclerk_workno]->Release();
            DBGPRINT(DEBUG_INFO, "the manager tell me to work on, ticketclerk %d start to work \n ", ticketclerk_workno);
			printf("TicketClerk [%d] is coming off break.\n", ticketclerk_workno);
        }
        ticketClerkLineLock->Acquire();// to get the lock of the line
        if(0==ticketclrk_cus_count[ticketclerk_workno]) //if no one is in the line
        {
            DBGPRINT(DEBUG_INFO,"ticket clerk %d is free right now, have a coffee and wait for the counter\n", ticketclerk_workno);
			printf("TicketClerk [%d] has no one in line. I am available for a customer.\n", ticketclerk_workno);
            ticketclrk_state[ticketclerk_workno]=0;
        }
        else //if some one
        {
            //step 1: dec the count of the customer line
            DBGPRINT(DEBUG_INFO,"ticket clerk %d need to wake up the customer\n", ticketclerk_workno);
			printf("TicketClerk [%d] has a line length [%d] and is signaling a customer.\n", ticketclerk_workno, ticketclrk_cus_count[ticketclerk_workno]);
            //step 2: wake up a customer from the list
            ticketclerkline_cv[ticketclerk_workno]->Signal(ticketClerkLineLock);
        }
        //step 3: wait for the customer to tell how many ticket do they want
        //right here we use a lock and condition to lock the global variables we are using, like ticket number and
        ticketClerkLineLock->Release();		//release the lock and wait for the customer to come
        ticketClerkMsgLock[ticketclerk_workno]->Acquire();
        ticketclerkMsg_cv[ticketclerk_workno]->Wait(ticketClerkMsgLock[ticketclerk_workno]);
        //right here, we need to check i am waked up by the customer to buy or the manager to break
        if(0==tickets_num[ticketclerk_workno]||OFF_WORK==ticketclrk_off[ticketclerk_workno])
            {
                DBGPRINT(DEBUG_INFO,"ticket clerk %d are told to off work or add a new line\n", ticketclerk_workno);
                ticketClerkMsgLock[ticketclerk_workno]->Release();
                goto checkOff;
            }
        //no, i am waked up by the customers, ok , let us work
        ticketClerkLineLock->Acquire();
        ticketclrk_state[ticketclerk_workno]=1;
        ticketclrk_cus_count[ticketclerk_workno]--;
        ticketClerkLineLock->Release();
        DBGPRINT(DEBUG_INFO,"ticket clerk %d say hi to the customer\n", ticketclerk_workno);
        //step 4: if there are, tell the customer how much it costs
        //waked up by the customer and read how many tickets do they want and caculate the money
        tickets_money[ticketclerk_workno]=TICKET_PRICE*tickets_num[ticketclerk_workno];
        totalCustomerLock->Acquire();
        totalCustomer+=tickets_num[ticketclerk_workno];
        ticketclrk_totalticksnum[ticketclerk_workno]+=tickets_num[ticketclerk_workno];
        totalCustomerLock->Release();
        
        DBGPRINT(DEBUG_INFO,"ticket clerk %d knows the customer want to buy %d tickets,  told the money is %d, total now is %d\n", ticketclerk_workno,tickets_num[ticketclerk_workno],tickets_money[ticketclerk_workno],ticketclrk_totalticksnum[ticketclerk_workno]);
		printf("TicketClerk [%d] has an order for [%d] and the cost is [%d].\n", ticketclerk_workno, tickets_num[ticketclerk_workno], tickets_money[ticketclerk_workno]);
        //wake up by the customer and receive the money
        ticketclerkMsg_cv[ticketclerk_workno]->Signal(ticketClerkMsgLock[ticketclerk_workno]);
        ticketClerkMsgLock[ticketclerk_workno]->Release();
		sendMoneyToManagerFromTicketClerk(ticketclerk_workno, tickets_num[ticketclerk_workno] * TICKET_PRICE);
		tickets_num[ticketclerk_workno]=0;
    }
};

